import json
from datetime import datetime


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


obj = {
    "key1": 100,
    "key2": 3.14,
    "key3": False,
    "key4": "hello",
    "key5": None,
    "key6": [1, 2, 3],
    "key7": (1, 2, 3),
    "key8": {"name": "abc"},
    "key9": {1, 2, 3},
    "key10": datetime.now(),
    "key11": Person("张三", 20)
}


class MyEncoder(json.JSONEncoder):
    def default(self, o):
        """
        默认不支持的数据类型会传入default 作为o
        :param o:
        :return:
        """
        if isinstance(o, datetime):
            return o.strftime("%Y-%m-%d %H:%M:%S")
        elif isinstance(o, set):
            return list(o)
        elif isinstance(o, Person):
            return {
                "name": o.name,
                "age": o.age
            }

        else:
            return "hello"


obj_str = json.dumps(obj, cls=MyEncoder, ensure_ascii=False)
print(obj_str)


class MyDecoder(json.JSONDecoder):
    def decode(self, s):
        # 先临时反序列化 得到字典
        temp = json.loads(s)

        # 针对字典中的特殊键处理
        p_dict = temp.pop("key11")
        p = Person(p_dict["name"], p_dict["age"])
        temp["key11"] = p

        time = temp.pop("key10")
        dt = datetime.strptime(time, "%Y-%m-%d %H:%M:%S")
        temp["key10"] = dt

        dates = temp.pop("key9")
        temp["key9"] = set(dates)
        return temp


obj2 = json.loads(obj_str, cls=MyDecoder)
print(obj2)
print(type(obj2["key9"]))
print(type(obj2["key10"]))
print(type(obj2["key11"]))